package com.dabai.iot.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dabai.common.core.exception.ServiceException;
import com.dabai.common.core.utils.Func;
import com.dabai.common.core.utils.StringUtils;
import com.dabai.iot.core.dto.ThingModelBlockUpdate;
import com.dabai.iot.core.entity.ProductEntity;
import com.dabai.iot.core.entity.ThingModelBlockEntity;
import com.dabai.iot.core.entity.ThingModelItemEntity;
import com.dabai.iot.core.mapper.ThingModelBlockMapper;
import com.dabai.iot.core.mapper.ThingModelItemMapper;
import com.dabai.iot.core.service.IProductService;
import com.dabai.iot.core.service.IThingModelBlockService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 物模型功能模块 Service 实现类
 *
 * @author kev1n
 */
@Service
@AllArgsConstructor
public class ThingModelBlockServiceImpl extends ServiceImpl<ThingModelBlockMapper, ThingModelBlockEntity> implements IThingModelBlockService {

    private final IProductService productService;
    private final ThingModelItemMapper thingModelItemMapper;

    @Override
    public boolean addModelBlock(ThingModelBlockEntity block) {
        ProductEntity product = productService.getProductCacheById(block.getProductId());
        if (product == null) {
            throw new ServiceException("产品不存在");
        }
        block.setProductKey(product.getProductKey());

        ThingModelBlockEntity entity = this.lambdaQuery()
            .eq(ThingModelBlockEntity::getTenantId, block.getTenantId())
            .eq(ThingModelBlockEntity::getProductId, block.getProductId())
            .eq(ThingModelBlockEntity::getBlockIdentifier, block.getBlockIdentifier())
            .one();
        if (entity != null) {
            // 已经存在相同的服务ID
            throw new ServiceException("已经存在相同的模块标识符");
        }
        return this.save(block);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateModelBlock(ThingModelBlockUpdate blockUpdate) {
        ThingModelBlockEntity block = getById(blockUpdate);
        if (block == null) {
            return false;
        }

        if ("DEFAULT".equals(block.getBlockIdentifier())) {
            // 默认物模型不可修改
            throw new ServiceException("默认物模型不可修改");
        }

        block.setBlockName(blockUpdate.getBlockName());

        boolean result = this.updateById(block);
        if (result) {
            result = productService.updateProductTsl(block.getProductId());
            if (!result) {
                // 更新物模型TSL失败
                throw new ServiceException("更新物模型 TSL 失败");
            }

        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeModelBlock(Long id) {
        // 判断下级
        Long itemsCount = thingModelItemMapper.selectCount(Wrappers.<ThingModelItemEntity>query().lambda().eq(ThingModelItemEntity::getBlockId, id));
        if (itemsCount > 0) {
            // 存在子项，不可删除
            throw new ServiceException(StringUtils.format("该物模型下还有({})个子项，无法删除", itemsCount));
        }

        ThingModelBlockEntity modelBlock = getById(id);
        if (modelBlock == null) {
            throw new ServiceException("物模型模块不存在");
        }

        if ("DEFAULT".equals(modelBlock.getBlockIdentifier())) {
            throw new ServiceException("默认模块不可修改");
        }

        boolean result = this.removeById(id);
        if (result) {
            result = productService.updateProductTsl(modelBlock.getProductId());
            if (!result) {
                throw new ServiceException("更新物模型 TSL 失败");
            }
        }
        return result;
    }

    @Override
    public IPage<ThingModelBlockEntity> getModelBlockPage(IPage<ThingModelBlockEntity> page, ThingModelBlockEntity thingModel) {
        QueryWrapper<ThingModelBlockEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
            .eq(Func.isNotEmpty(thingModel.getId()), ThingModelBlockEntity::getId, thingModel.getId())
            .eq(Func.isNotEmpty(thingModel.getTenantId()), ThingModelBlockEntity::getTenantId, thingModel.getTenantId())
            .eq(Func.isNotEmpty(thingModel.getProductId()), ThingModelBlockEntity::getProductId, thingModel.getProductId())
            .eq(Func.isNotEmpty(thingModel.getBlockIdentifier()), ThingModelBlockEntity::getBlockIdentifier, thingModel.getBlockIdentifier())
            .like(Func.isNotEmpty(thingModel.getBlockName()), ThingModelBlockEntity::getBlockName, thingModel.getBlockName());

        return page(page, queryWrapper);
    }

}
